Libraries laden

library(tidyverse)
library(readr)
library(broom)
library(gridExtra)
library(stats)
library(janitor)
library(skimr)
library(lubridate)
getwd()
[1] "C:/DHBW/Semester3/DataScience/Weiner_inf24_Passanten"

Passanten in Würzburg

Import und Datenbereinigung

zuerst importiert man die Daten und zeigt Sie an um zu überprüfen ob der import funktioniert hat.

passanten_raw <- read_csv2("Datensatz/passanten_wuerzburg.csv")
passanten <- as_tibble(passanten_raw)
passanten

Nun besitzt man die Daten als Dataframe. Um mit ihnen sinvolle, descriptive oder weiterführend eine Explorative Datenanalyse durchzuführen sollten die Daten zuerst bereinigt werden. Als nächstes prüfen wir ob die Spalentnamen Aussagekräfig sind und ändern sie ab falls notwendig

names(passanten)
 [1] "Zeitstempel"              "Wetter"                   "Temperatur"               "Passanten"                "Location Name"           
 [6] "GeoPunkt"                 "Passanten ltr"            "Passanten rtl"            "Passanten Erwachsene"     "Passanten Kinder"        
[11] "Passanten Erwachsene ltr" "Passanten Erwachsene rtl" "Passanten Kinder ltr"     "Passanten Kinder rtl"    
#Formatieren Spalten Namen
passanten <- clean_names(passanten)
passanten

Somit können wir nun leer Spalten entfernen und nachsehen wie vollständig die Daten sind.

#Aufzählung der NA nach Spalte
colSums(is.na(passanten))
             zeitstempel                   wetter               temperatur                passanten            location_name                geo_punkt 
                       0                      112                      112                        0                        0                        0 
           passanten_ltr            passanten_rtl     passanten_erwachsene         passanten_kinder passanten_erwachsene_ltr passanten_erwachsene_rtl 
                   11395                    11395                    11395                    11395                    11395                    11395 
    passanten_kinder_ltr     passanten_kinder_rtl 
                   11395                    11395 
nrow(passanten)
[1] 26018
#Entfernen leere Spalten
passanten <- janitor::remove_empty(passanten)
nrow(passanten)
[1] 26018

#Die Gehrichtung und erkennung der erwachsenen / kinder fehlt bei 11395 Zeilen. Unvollständige daten bis dahin.Kein komplett leere spalte gefunden. Anschließend Prüfen wir die Datentypen und Einheiten die die Spalten haben.

passanten <- passanten %>% 
  mutate(
    temperatur = as.numeric(temperatur),
    passanten = as.numeric(passanten),
    zeitstempel = as.Date(zeitstempel)
  )

Zum Schluss erhalten wir eine übersicht über die Daten

summary(passanten)
  zeitstempel            wetter            temperatur       passanten      location_name       geo_punkt         passanten_ltr    passanten_rtl   
 Min.   :2023-12-31   Length:26018       Min.   :-11.00   Min.   :   0.0   Length:26018       Length:26018       Min.   :   0.0   Min.   :   0.0  
 1st Qu.:2024-03-31   Class :character   1st Qu.:  5.50   1st Qu.:  53.0   Class :character   Class :character   1st Qu.:  24.0   1st Qu.:  27.0  
 Median :2024-06-30   Mode  :character   Median : 10.70   Median : 467.0   Mode  :character   Mode  :character   Median : 233.0   Median : 263.0  
 Mean   :2024-07-01                      Mean   : 11.26   Mean   : 840.5                                         Mean   : 438.4   Mean   : 454.4  
 3rd Qu.:2024-10-01                      3rd Qu.: 17.00   3rd Qu.:1341.0                                         3rd Qu.: 676.0   3rd Qu.: 750.0  
 Max.   :2024-12-31                      Max.   : 34.00   Max.   :8075.0                                         Max.   :4461.0   Max.   :3614.0  
                                         NA's   :112                                                             NA's   :11395    NA's   :11395   
 passanten_erwachsene passanten_kinder passanten_erwachsene_ltr passanten_erwachsene_rtl passanten_kinder_ltr passanten_kinder_rtl
 Min.   :   0.0       Min.   :  0.00   Min.   :   0.0           Min.   :   0.0           Min.   :  0.00       Min.   : 0.000      
 1st Qu.:  51.0       1st Qu.:  1.00   1st Qu.:  24.0           1st Qu.:  26.0           1st Qu.:  0.00       1st Qu.: 0.000      
 Median : 499.0       Median :  7.00   Median : 229.0           Median : 258.0           Median :  3.00       Median : 4.000      
 Mean   : 877.5       Mean   : 15.31   Mean   : 431.2           Mean   : 446.3           Mean   :  7.24       Mean   : 8.075      
 3rd Qu.:1392.5       3rd Qu.: 26.00   3rd Qu.: 661.0           3rd Qu.: 734.0           3rd Qu.: 12.00       3rd Qu.:14.000      
 Max.   :7933.0       Max.   :179.00   Max.   :4375.0           Max.   :3558.0           Max.   :118.00       Max.   :77.000      
 NA's   :11395        NA's   :11395    NA's   :11395            NA's   :11395            NA's   :11395        NA's   :11395       
skimr::skim(passanten)
── Data Summary ────────────────────────
                           Values   
Name                       passanten
Number of rows             26018    
Number of columns          14       
_______________________             
Column type frequency:              
  character                3        
  Date                     1        
  numeric                  10       
________________________            
Group variables            None     

Aufgabe 1

Beschreibung der Daten

Der Datensatz besteht aus 26018 Zeile und 14 Spalten.Die in den Spalten aufgezeichneten werte sind:

head(passanten)

Die interessantest Variable ist hierbei die anzahl der Passanten. Dabei werden hir die anzahl der Passanten mit jewails eine Zeitstempel und weiteren Metadaten wie: Temperatur, Ort der Aufzeichnung und Koordinaten des Ortes Zeilenweise angegeben. Die Zeitstempel sind dabei Stündlich für jede der drei Messtationen angegeben.

table(passanten$location_name)

   Kaiserstraße Schönbornstraße   Spiegelstraße 
           8695            8649            8674 

Somit kann man davon ausgehen das die anzahl der Passanten der anzahl der Passanten entspricht die inerhalb einer Stunde durch die Messtation erfasst wurden. Die Metadaten dienen dann zur Interpretation der Hauptdaten.

Erhebung

Die Daten stamen von zählstationen an verschiedenen Punken aus der Nürnberger Innenstadt. Mit hilfe von Laserschranken zählen diese die Anzahl der Passanten welche gerade die Messtation Queren. Durch das Messen mit meheren Laserschranken pro Messtation kann auch die Geh-Richtung des Passanten bestimmt werden. Zur konsistenz der Daten wird vermerkt: “Nach Herstellerangabe kann mit der verwendeten Technik bis zu einem Durchfluss von ca. 500 Personen pro Minute eine Zählgenauigkeit von 99% erreicht werden.” vgl. Methodik_hystreet.com. Dabei ist zu beachten, dass eine Zählstation eine Straße bis Maximal 32m Breite abdecken kann. Die Erheber der daten versichern jedoch, dass “Bei den veröffentlichten Daten handelt es sich immer um die Passantenfrequenz der gesamten Straßenbreite (außer es ist explizit anders angegeben).”

Standorte

table(passanten$geo_punkt)

 49.79512717222457, 9.934114106308467 49.795490162266525, 9.931060093195851 49.798498976405355, 9.933887635731686 
                                 8674                                  8649                                  8695 
table(passanten$location_name)

   Kaiserstraße Schönbornstraße   Spiegelstraße 
           8695            8649            8674 

Der Datenstatz enthält Koordinaten in der Spalte geo_punkt und die orte der Messtationen in der Spalte location_name. Wenn man sich anschaut wie of eine einzelner Standort vorkommt sieht man, dass es jewail 3 Einzelne Standorte gibt und dazu passend die 3 Standorte in Koordinatenform. Die Summen (Wie oft ein Einzelner eintrag vorkommt) ist ebenfalls gleich. Somit ist eine eindeutige zuordung der Standorte zu den Koordinaten möglich. Gleichzeit können wir sicher sein das keine Falschen Standorte oder Koordinaten vorliegen und das jeder Standort auch mit den Korrekten Korrdinaten versehen sind.Wenn man nun die Koordinaten auf einer Karte anzeigen Lässt erhält man folgendes Bild.

Man kann sehen, das die Stationen direkt in der Innenstad stationiert sind. Dabei ist jede Station in der Nähe einer Sehenswürdigkeit bzw. Öffentlichen Gebäude. Die Messtation Schönbornstraße befindet sich nah an der Marienkapelle, die Messtation Spiegelstraße auf dem weg zum Hofgarten und die Messtation Kaiserstraße in der nähe zum Hauptbahnhof. Dabei sind alle diese Straßen Hauptverkehrsstraßen auf welchen man mit gleichmäsiger auslastung rechnen kann. Das Dreiecksmuster welche die Stationen Aufspannen bilden somit eine Art Transitstrecke zwischen: Hauptbahnhof -> Hofgarten -> Marienkapelle -> Hauptbahnhof.

Aufgabe 2

# --- 1. Analyse gegliedert nach Messstellen ---
# (Wie in deinem Code-Ansatz begonnen)

# Wir gruppieren nach dem Standortnamen
passanten_pro_location <- passanten %>%
  group_by(location_name) %>%
  summarise(
    
    # 1. Jahressumme pro Standort
    # Wir summieren alle Werte in der 'passanten'-Spalte für die jeweilige Gruppe
    passanten_jahr_summe = sum(passanten, na.rm = TRUE),
    
    # Hilfsberechnung: Anzahl der einzigartigen Tage, an denen Daten erfasst wurden
    # as.Date() wandelt den Zeitstempel in ein reines Datum um
    # n_distinct() zählt, wie viele einzigartige Tage es gibt
    anzahl_tage_erfasst = n_distinct(as.Date(zeitstempel)),
    
    # 2. Mittelwert pro Monat
    # Wir nehmen die Jahressumme und teilen sie durch 12 Monate
    durchschnitt_pro_monat = passanten_jahr_summe / 12,
    
    # 3. Mittelwert pro Woche
    # Wir teilen die Jahressumme durch die Anzahl der Wochen im Jahr
    # (Anzahl Tage / 7 Tage pro Woche)
    durchschnitt_pro_woche = passanten_jahr_summe / (anzahl_tage_erfasst / 7),

    # 4. Mittelwert pro Tag
    # Wir teilen die Jahressumme durch die Anzahl der erfassten Tage
    durchschnitt_pro_tag = passanten_jahr_summe / anzahl_tage_erfasst,
    
    # 5. Mittelwert pro Stunde
    # Da die Rohdaten bereits stündlich sind, ist dies der 
    # einfache Mittelwert der 'passanten'-Spalte
    durchschnitt_pro_stunde = mean(passanten, na.rm = TRUE)
  )

# --- 2. Analyse aggregiert (insgesamt) ---
# (Hier fassen wir alle Messstellen zusammen, indem wir group_by() weglassen)

passanten_insgesamt <- passanten %>%
  summarise(
    
    # 1. Jahressumme (Gesamt)
    passanten_jahr_summe = sum(passanten, na.rm = TRUE),
    
    # Hilfsberechnung: Anzahl der einzigartigen Tage im gesamten Datensatz
    anzahl_tage_erfasst = n_distinct(as.Date(zeitstempel)),

    # 2. Mittelwert pro Monat (Gesamt)
    durchschnitt_pro_monat = passanten_jahr_summe / 12,
    
    # 3. Mittelwert pro Woche (Gesamt)
    durchschnitt_pro_woche = passanten_jahr_summe / (anzahl_tage_erfasst / 7),
    
    # 4. Mittelwert pro Tag (Gesamt)
    durchschnitt_pro_tag = passanten_jahr_summe / anzahl_tage_erfasst,
    
    # 5. Mittelwert pro Stunde (Gesamt)
    durchschnitt_pro_stunde = mean(passanten, na.rm = TRUE)
  )

passanten_pro_location
passanten_insgesamt

Literatur

https://studyflix.de/statistik/mittelwert-6133

LS0tDQp0aXRsZTogIldlaW5lcl9QYXNzYW50ZW4wMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KTGlicmFyaWVzIGxhZGVuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KbGlicmFyeShzdGF0cykNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoc2tpbXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmBgYA0KDQpgYGB7cn0NCmdldHdkKCkNCmBgYA0KDQojIFBhc3NhbnRlbiBpbiBXw7xyemJ1cmcNCg0KIyMgSW1wb3J0IHVuZCBEYXRlbmJlcmVpbmlndW5nDQoNCnp1ZXJzdCBpbXBvcnRpZXJ0IG1hbiBkaWUgRGF0ZW4gdW5kIHplaWd0IFNpZSBhbiB1bSB6dSDDvGJlcnByw7xmZW4gb2IgZGVyIGltcG9ydCBmdW5rdGlvbmllcnQgaGF0Lg0KDQpgYGB7cn0NCnBhc3NhbnRlbl9yYXcgPC0gcmVhZF9jc3YyKCJEYXRlbnNhdHovcGFzc2FudGVuX3d1ZXJ6YnVyZy5jc3YiKQ0KcGFzc2FudGVuIDwtIGFzX3RpYmJsZShwYXNzYW50ZW5fcmF3KQ0KcGFzc2FudGVuDQpgYGANCg0KTnVuIGJlc2l0enQgbWFuIGRpZSBEYXRlbiBhbHMgRGF0YWZyYW1lLiBVbSBtaXQgaWhuZW4gc2ludm9sbGUsIGRlc2NyaXB0aXZlIG9kZXIgd2VpdGVyZsO8aHJlbmQgZWluZSBFeHBsb3JhdGl2ZSBEYXRlbmFuYWx5c2UgZHVyY2h6dWbDvGhyZW4gc29sbHRlbiBkaWUgRGF0ZW4genVlcnN0IGJlcmVpbmlndCB3ZXJkZW4uIEFscyBuw6RjaHN0ZXMgcHLDvGZlbiB3aXIgb2IgZGllIFNwYWxlbnRuYW1lbiBBdXNzYWdla3LDpGZpZyBzaW5kIHVuZCDDpG5kZXJuIHNpZSBhYiBmYWxscyBub3R3ZW5kaWcNCg0KYGBge3J9DQpuYW1lcyhwYXNzYW50ZW4pDQojRm9ybWF0aWVyZW4gU3BhbHRlbiBOYW1lbg0KcGFzc2FudGVuIDwtIGNsZWFuX25hbWVzKHBhc3NhbnRlbikNCnBhc3NhbnRlbg0KYGBgDQoNClNvbWl0IGvDtm5uZW4gd2lyIG51biBsZWVyIFNwYWx0ZW4gZW50ZmVybmVuIHVuZCBuYWNoc2VoZW4gd2llIHZvbGxzdMOkbmRpZyBkaWUgRGF0ZW4gc2luZC4NCg0KYGBge3J9DQojQXVmesOkaGx1bmcgZGVyIE5BIG5hY2ggU3BhbHRlDQpjb2xTdW1zKGlzLm5hKHBhc3NhbnRlbikpDQpucm93KHBhc3NhbnRlbikNCiNFbnRmZXJuZW4gbGVlcmUgU3BhbHRlbg0KcGFzc2FudGVuIDwtIGphbml0b3I6OnJlbW92ZV9lbXB0eShwYXNzYW50ZW4pDQpucm93KHBhc3NhbnRlbikNCmBgYA0KDQojRGllIEdlaHJpY2h0dW5nIHVuZCBlcmtlbm51bmcgZGVyIGVyd2FjaHNlbmVuIC8ga2luZGVyIGZlaGx0IGJlaSAxMTM5NSBaZWlsZW4uIFVudm9sbHN0w6RuZGlnZSBkYXRlbiBiaXMgZGFoaW4uS2VpbiBrb21wbGV0dCBsZWVyZSBzcGFsdGUgZ2VmdW5kZW4uIEFuc2NobGllw59lbmQgUHLDvGZlbiB3aXIgZGllIERhdGVudHlwZW4gdW5kIEVpbmhlaXRlbiBkaWUgZGllIFNwYWx0ZW4gaGFiZW4uDQoNCmBgYHtyfQ0KcGFzc2FudGVuIDwtIHBhc3NhbnRlbiAlPiUgDQogIG11dGF0ZSgNCiAgICB0ZW1wZXJhdHVyID0gYXMubnVtZXJpYyh0ZW1wZXJhdHVyKSwNCiAgICBwYXNzYW50ZW4gPSBhcy5udW1lcmljKHBhc3NhbnRlbiksDQogICAgemVpdHN0ZW1wZWwgPSBhcy5EYXRlKHplaXRzdGVtcGVsKQ0KICApDQpgYGANCg0KWnVtIFNjaGx1c3MgZXJoYWx0ZW4gd2lyIGVpbmUgw7xiZXJzaWNodCDDvGJlciBkaWUgRGF0ZW4NCg0KYGBge3J9DQpzdW1tYXJ5KHBhc3NhbnRlbikNCnNraW1yOjpza2ltKHBhc3NhbnRlbikNCmBgYA0KDQojIyBBdWZnYWJlIDENCg0KIyMgQmVzY2hyZWlidW5nIGRlciBEYXRlbg0KDQpEZXIgRGF0ZW5zYXR6IGJlc3RlaHQgYXVzIDI2MDE4IFplaWxlIHVuZCAxNCBTcGFsdGVuLkRpZSBpbiBkZW4gU3BhbHRlbiBhdWZnZXplaWNobmV0ZW4gd2VydGUgc2luZDoNCg0KYGBge3J9DQpoZWFkKHBhc3NhbnRlbikNCmBgYA0KDQpEaWUgaW50ZXJlc3NhbnRlc3QgVmFyaWFibGUgaXN0IGhpZXJiZWkgZGllIGFuemFobCBkZXIgUGFzc2FudGVuLiBEYWJlaSB3ZXJkZW4gaGlyIGRpZSBhbnphaGwgZGVyIFBhc3NhbnRlbiBtaXQgamV3YWlscyBlaW5lIFplaXRzdGVtcGVsIHVuZCB3ZWl0ZXJlbiBNZXRhZGF0ZW4gd2llOiBUZW1wZXJhdHVyLCBPcnQgZGVyIEF1ZnplaWNobnVuZyB1bmQgS29vcmRpbmF0ZW4gZGVzIE9ydGVzIFplaWxlbndlaXNlIGFuZ2VnZWJlbi4gRGllIFplaXRzdGVtcGVsIHNpbmQgZGFiZWkgU3TDvG5kbGljaCBmw7xyIGplZGUgZGVyIGRyZWkgTWVzc3RhdGlvbmVuIGFuZ2VnZWJlbi4NCg0KYGBge3J9DQp0YWJsZShwYXNzYW50ZW4kbG9jYXRpb25fbmFtZSkNCmBgYA0KDQpTb21pdCBrYW5uIG1hbiBkYXZvbiBhdXNnZWhlbiBkYXMgZGllIGFuemFobCBkZXIgUGFzc2FudGVuIGRlciBhbnphaGwgZGVyIFBhc3NhbnRlbiBlbnRzcHJpY2h0IGRpZSBpbmVyaGFsYiBlaW5lciBTdHVuZGUgZHVyY2ggZGllIE1lc3N0YXRpb24gZXJmYXNzdCB3dXJkZW4uIERpZSBNZXRhZGF0ZW4gZGllbmVuIGRhbm4genVyIEludGVycHJldGF0aW9uIGRlciBIYXVwdGRhdGVuLg0KDQojIyMgRXJoZWJ1bmcNCg0KRGllIERhdGVuIHN0YW1lbiB2b24gesOkaGxzdGF0aW9uZW4gYW4gdmVyc2NoaWVkZW5lbiBQdW5rZW4gYXVzIGRlciBOw7xybmJlcmdlciBJbm5lbnN0YWR0LiBNaXQgaGlsZmUgdm9uIExhc2Vyc2NocmFua2VuIHrDpGhsZW4gZGllc2UgZGllIEFuemFobCBkZXIgUGFzc2FudGVuIHdlbGNoZSBnZXJhZGUgZGllIE1lc3N0YXRpb24gUXVlcmVuLiBEdXJjaCBkYXMgTWVzc2VuIG1pdCBtZWhlcmVuIExhc2Vyc2NocmFua2VuIHBybyBNZXNzdGF0aW9uIGthbm4gYXVjaCBkaWUgR2VoLVJpY2h0dW5nIGRlcyBQYXNzYW50ZW4gYmVzdGltbXQgd2VyZGVuLiBadXIga29uc2lzdGVueiBkZXIgRGF0ZW4gd2lyZCB2ZXJtZXJrdDogIk5hY2ggSGVyc3RlbGxlcmFuZ2FiZSBrYW5uIG1pdCBkZXIgdmVyd2VuZGV0ZW4gVGVjaG5payBiaXMgenUgZWluZW0gRHVyY2hmbHVzcyB2b24gY2EuIDUwMCBQZXJzb25lbiBwcm8gTWludXRlIGVpbmUgWsOkaGxnZW5hdWlna2VpdCB2b24gOTklIGVycmVpY2h0IHdlcmRlbi4iIHZnbC4gTWV0aG9kaWtfaHlzdHJlZXQuY29tLiBEYWJlaSBpc3QgenUgYmVhY2h0ZW4sIGRhc3MgZWluZSBaw6RobHN0YXRpb24gZWluZSBTdHJhw59lIGJpcyBNYXhpbWFsIDMybSBCcmVpdGUgYWJkZWNrZW4ga2Fubi4gRGllIEVyaGViZXIgZGVyIGRhdGVuIHZlcnNpY2hlcm4gamVkb2NoLCBkYXNzICJCZWkgZGVuIHZlcsO2ZmZlbnRsaWNodGVuIERhdGVuIGhhbmRlbHQgZXMgc2ljaCBpbW1lciB1bSBkaWUgUGFzc2FudGVuZnJlcXVlbnogZGVyIGdlc2FtdGVuIFN0cmHDn2VuYnJlaXRlIChhdcOfZXIgZXMgaXN0IGV4cGxpeml0IGFuZGVycyBhbmdlZ2ViZW4pLiINCg0KIyMjIFN0YW5kb3J0ZQ0KDQpgYGB7cn0NCnRhYmxlKHBhc3NhbnRlbiRnZW9fcHVua3QpDQp0YWJsZShwYXNzYW50ZW4kbG9jYXRpb25fbmFtZSkNCmBgYA0KDQpEZXIgRGF0ZW5zdGF0eiBlbnRow6RsdCBLb29yZGluYXRlbiBpbiBkZXIgU3BhbHRlIGdlb19wdW5rdCB1bmQgZGllIG9ydGUgZGVyIE1lc3N0YXRpb25lbiBpbiBkZXIgU3BhbHRlIGxvY2F0aW9uX25hbWUuIFdlbm4gbWFuIHNpY2ggYW5zY2hhdXQgd2llIG9mIGVpbmUgZWluemVsbmVyIFN0YW5kb3J0IHZvcmtvbW10IHNpZWh0IG1hbiwgZGFzcyBlcyBqZXdhaWwgMyBFaW56ZWxuZSBTdGFuZG9ydGUgZ2lidCB1bmQgZGF6dSBwYXNzZW5kIGRpZSAzIFN0YW5kb3J0ZSBpbiBLb29yZGluYXRlbmZvcm0uIERpZSBTdW1tZW4gKFdpZSBvZnQgZWluIEVpbnplbG5lciBlaW50cmFnIHZvcmtvbW10KSBpc3QgZWJlbmZhbGxzIGdsZWljaC4gU29taXQgaXN0IGVpbmUgZWluZGV1dGlnZSB6dW9yZHVuZyBkZXIgU3RhbmRvcnRlIHp1IGRlbiBLb29yZGluYXRlbiBtw7ZnbGljaC4gR2xlaWNoemVpdCBrw7ZubmVuIHdpciBzaWNoZXIgc2VpbiBkYXMga2VpbmUgRmFsc2NoZW4gU3RhbmRvcnRlIG9kZXIgS29vcmRpbmF0ZW4gdm9ybGllZ2VuIHVuZCBkYXMgamVkZXIgU3RhbmRvcnQgYXVjaCBtaXQgZGVuIEtvcnJla3RlbiBLb3JyZGluYXRlbiB2ZXJzZWhlbiBzaW5kLldlbm4gbWFuIG51biBkaWUgS29vcmRpbmF0ZW4gYXVmIGVpbmVyIEthcnRlIGFuemVpZ2VuIEzDpHNzdCBlcmjDpGx0IG1hbiBmb2xnZW5kZXMgQmlsZC4NCg0KYGBge3IgYmlsZC1laW5mdWVnZW4sIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIiwgZmlnLmNhcD0iSGllciBzdGVodCBkaWUgQmlsZHVudGVyc2NocmlmdC4ifQ0KIyBlY2hvPUZBTFNFIHZlcnN0ZWNrdCBkZW4gUi1Db2RlIGltIGZpbmFsZW4gRG9rdW1lbnQNCiMgb3V0LndpZHRoPSI1MCUiIHNldHp0IGRpZSBCcmVpdGUNCiMgZmlnLmNhcD0iLi4uIiBmw7xndCBlaW5lIFVudGVyc2NocmlmdCBoaW56dQ0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQmlsZGVyL3d1ZXJ6YnVyZ19zdGFkdHBsYW5fbWVzc3RhdGlvbmVuLnBuZyIpDQpgYGANCk1hbiBrYW5uIHNlaGVuLCBkYXMgZGllIFN0YXRpb25lbiBkaXJla3QgaW4gZGVyIElubmVuc3RhZCBzdGF0aW9uaWVydCBzaW5kLiBEYWJlaSBpc3QgamVkZSBTdGF0aW9uIGluIGRlciBOw6RoZSBlaW5lciBTZWhlbnN3w7xyZGlna2VpdCBiencuIMOWZmZlbnRsaWNoZW4gR2Viw6R1ZGUuIERpZSBNZXNzdGF0aW9uIFNjaMO2bmJvcm5zdHJhw59lIGJlZmluZGV0IHNpY2ggbmFoIGFuIGRlciBNYXJpZW5rYXBlbGxlLCBkaWUgTWVzc3RhdGlvbiBTcGllZ2Vsc3RyYcOfZSBhdWYgZGVtIHdlZyB6dW0gSG9mZ2FydGVuIHVuZCBkaWUgTWVzc3RhdGlvbiBLYWlzZXJzdHJhw59lIGluIGRlciBuw6RoZSB6dW0gSGF1cHRiYWhuaG9mLiBEYWJlaSBzaW5kIGFsbGUgZGllc2UgU3RyYcOfZW4gSGF1cHR2ZXJrZWhyc3N0cmHDn2VuIGF1ZiB3ZWxjaGVuIG1hbiBtaXQgZ2xlaWNobcOkc2lnZXIgYXVzbGFzdHVuZyByZWNobmVuIGthbm4uIERhcyBEcmVpZWNrc211c3RlciB3ZWxjaGUgZGllIFN0YXRpb25lbiBBdWZzcGFubmVuIGJpbGRlbiBzb21pdCBlaW5lIEFydCBUcmFuc2l0c3RyZWNrZSB6d2lzY2hlbjogSGF1cHRiYWhuaG9mIC0+IEhvZmdhcnRlbiAtPiBNYXJpZW5rYXBlbGxlIC0+IEhhdXB0YmFobmhvZi4NCg0KIyMgQXVmZ2FiZSAyDQoNCmBgYGB7cn0NCiMgLS0tIDEuIEFuYWx5c2UgZ2VnbGllZGVydCBuYWNoIE1lc3NzdGVsbGVuIC0tLQ0KIyAoV2llIGluIGRlaW5lbSBDb2RlLUFuc2F0eiBiZWdvbm5lbikNCg0KIyBXaXIgZ3J1cHBpZXJlbiBuYWNoIGRlbSBTdGFuZG9ydG5hbWVuDQpwYXNzYW50ZW5fcHJvX2xvY2F0aW9uIDwtIHBhc3NhbnRlbiAlPiUNCiAgZ3JvdXBfYnkobG9jYXRpb25fbmFtZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICANCiAgICAjIDEuIEphaHJlc3N1bW1lIHBybyBTdGFuZG9ydA0KICAgICMgV2lyIHN1bW1pZXJlbiBhbGxlIFdlcnRlIGluIGRlciAncGFzc2FudGVuJy1TcGFsdGUgZsO8ciBkaWUgamV3ZWlsaWdlIEdydXBwZQ0KICAgIHBhc3NhbnRlbl9qYWhyX3N1bW1lID0gc3VtKHBhc3NhbnRlbiwgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICAjIEhpbGZzYmVyZWNobnVuZzogQW56YWhsIGRlciBlaW56aWdhcnRpZ2VuIFRhZ2UsIGFuIGRlbmVuIERhdGVuIGVyZmFzc3Qgd3VyZGVuDQogICAgIyBhcy5EYXRlKCkgd2FuZGVsdCBkZW4gWmVpdHN0ZW1wZWwgaW4gZWluIHJlaW5lcyBEYXR1bSB1bQ0KICAgICMgbl9kaXN0aW5jdCgpIHrDpGhsdCwgd2llIHZpZWxlIGVpbnppZ2FydGlnZSBUYWdlIGVzIGdpYnQNCiAgICBhbnphaGxfdGFnZV9lcmZhc3N0ID0gbl9kaXN0aW5jdChhcy5EYXRlKHplaXRzdGVtcGVsKSksDQogICAgDQogICAgIyAyLiBNaXR0ZWx3ZXJ0IHBybyBNb25hdA0KICAgICMgV2lyIG5laG1lbiBkaWUgSmFocmVzc3VtbWUgdW5kIHRlaWxlbiBzaWUgZHVyY2ggMTIgTW9uYXRlDQogICAgZHVyY2hzY2huaXR0X3Byb19tb25hdCA9IHBhc3NhbnRlbl9qYWhyX3N1bW1lIC8gMTIsDQogICAgDQogICAgIyAzLiBNaXR0ZWx3ZXJ0IHBybyBXb2NoZQ0KICAgICMgV2lyIHRlaWxlbiBkaWUgSmFocmVzc3VtbWUgZHVyY2ggZGllIEFuemFobCBkZXIgV29jaGVuIGltIEphaHINCiAgICAjIChBbnphaGwgVGFnZSAvIDcgVGFnZSBwcm8gV29jaGUpDQogICAgZHVyY2hzY2huaXR0X3Byb193b2NoZSA9IHBhc3NhbnRlbl9qYWhyX3N1bW1lIC8gKGFuemFobF90YWdlX2VyZmFzc3QgLyA3KSwNCg0KICAgICMgNC4gTWl0dGVsd2VydCBwcm8gVGFnDQogICAgIyBXaXIgdGVpbGVuIGRpZSBKYWhyZXNzdW1tZSBkdXJjaCBkaWUgQW56YWhsIGRlciBlcmZhc3N0ZW4gVGFnZQ0KICAgIGR1cmNoc2Nobml0dF9wcm9fdGFnID0gcGFzc2FudGVuX2phaHJfc3VtbWUgLyBhbnphaGxfdGFnZV9lcmZhc3N0LA0KICAgIA0KICAgICMgNS4gTWl0dGVsd2VydCBwcm8gU3R1bmRlDQogICAgIyBEYSBkaWUgUm9oZGF0ZW4gYmVyZWl0cyBzdMO8bmRsaWNoIHNpbmQsIGlzdCBkaWVzIGRlciANCiAgICAjIGVpbmZhY2hlIE1pdHRlbHdlcnQgZGVyICdwYXNzYW50ZW4nLVNwYWx0ZQ0KICAgIGR1cmNoc2Nobml0dF9wcm9fc3R1bmRlID0gbWVhbihwYXNzYW50ZW4sIG5hLnJtID0gVFJVRSkNCiAgKQ0KDQojIC0tLSAyLiBBbmFseXNlIGFnZ3JlZ2llcnQgKGluc2dlc2FtdCkgLS0tDQojIChIaWVyIGZhc3NlbiB3aXIgYWxsZSBNZXNzc3RlbGxlbiB6dXNhbW1lbiwgaW5kZW0gd2lyIGdyb3VwX2J5KCkgd2VnbGFzc2VuKQ0KDQpwYXNzYW50ZW5faW5zZ2VzYW10IDwtIHBhc3NhbnRlbiAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIA0KICAgICMgMS4gSmFocmVzc3VtbWUgKEdlc2FtdCkNCiAgICBwYXNzYW50ZW5famFocl9zdW1tZSA9IHN1bShwYXNzYW50ZW4sIG5hLnJtID0gVFJVRSksDQogICAgDQogICAgIyBIaWxmc2JlcmVjaG51bmc6IEFuemFobCBkZXIgZWluemlnYXJ0aWdlbiBUYWdlIGltIGdlc2FtdGVuIERhdGVuc2F0eg0KICAgIGFuemFobF90YWdlX2VyZmFzc3QgPSBuX2Rpc3RpbmN0KGFzLkRhdGUoemVpdHN0ZW1wZWwpKSwNCg0KICAgICMgMi4gTWl0dGVsd2VydCBwcm8gTW9uYXQgKEdlc2FtdCkNCiAgICBkdXJjaHNjaG5pdHRfcHJvX21vbmF0ID0gcGFzc2FudGVuX2phaHJfc3VtbWUgLyAxMiwNCiAgICANCiAgICAjIDMuIE1pdHRlbHdlcnQgcHJvIFdvY2hlIChHZXNhbXQpDQogICAgZHVyY2hzY2huaXR0X3Byb193b2NoZSA9IHBhc3NhbnRlbl9qYWhyX3N1bW1lIC8gKGFuemFobF90YWdlX2VyZmFzc3QgLyA3KSwNCiAgICANCiAgICAjIDQuIE1pdHRlbHdlcnQgcHJvIFRhZyAoR2VzYW10KQ0KICAgIGR1cmNoc2Nobml0dF9wcm9fdGFnID0gcGFzc2FudGVuX2phaHJfc3VtbWUgLyBhbnphaGxfdGFnZV9lcmZhc3N0LA0KICAgIA0KICAgICMgNS4gTWl0dGVsd2VydCBwcm8gU3R1bmRlIChHZXNhbXQpDQogICAgZHVyY2hzY2huaXR0X3Byb19zdHVuZGUgPSBtZWFuKHBhc3NhbnRlbiwgbmEucm0gPSBUUlVFKQ0KICApDQoNCnBhc3NhbnRlbl9wcm9fbG9jYXRpb24NCmBgYGANCg0KDQojIExpdGVyYXR1cg0KaHR0cHM6Ly9zdHVkeWZsaXguZGUvc3RhdGlzdGlrL21pdHRlbHdlcnQtNjEzMw0K